1#![stable(feature = "io_safety", since = "1.63.0")]
4
5use super::raw::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
6use crate::alloc::Allocator;
7use crate::marker::PhantomData;
8use crate::mem::ManuallyDrop;
9use crate::sys::{AsInner, FromInner, IntoInner, cvt};
10use crate::{fmt, fs, io, ptr, sys};
11
12#[derive(Copy, Clone)]
36#[repr(transparent)]
37#[stable(feature = "io_safety", since = "1.63.0")]
38pub struct BorrowedHandle<'handle> {
39 handle: RawHandle,
40 _phantom: PhantomData<&'handle OwnedHandle>,
41}
42
43#[repr(transparent)]
65#[stable(feature = "io_safety", since = "1.63.0")]
66pub struct OwnedHandle {
67 handle: RawHandle,
68}
69
70#[repr(transparent)]
88#[stable(feature = "io_safety", since = "1.63.0")]
89#[derive(Debug)]
90pub struct HandleOrNull(RawHandle);
91
92#[repr(transparent)]
107#[stable(feature = "io_safety", since = "1.63.0")]
108#[derive(Debug)]
109pub struct HandleOrInvalid(RawHandle);
110
111#[stable(feature = "io_safety", since = "1.63.0")]
117unsafe impl Send for OwnedHandle {}
118#[stable(feature = "io_safety", since = "1.63.0")]
119unsafe impl Send for HandleOrNull {}
120#[stable(feature = "io_safety", since = "1.63.0")]
121unsafe impl Send for HandleOrInvalid {}
122#[stable(feature = "io_safety", since = "1.63.0")]
123unsafe impl Send for BorrowedHandle<'_> {}
124#[stable(feature = "io_safety", since = "1.63.0")]
125unsafe impl Sync for OwnedHandle {}
126#[stable(feature = "io_safety", since = "1.63.0")]
127unsafe impl Sync for HandleOrNull {}
128#[stable(feature = "io_safety", since = "1.63.0")]
129unsafe impl Sync for HandleOrInvalid {}
130#[stable(feature = "io_safety", since = "1.63.0")]
131unsafe impl Sync for BorrowedHandle<'_> {}
132
133impl BorrowedHandle<'_> {
134 #[inline]
149 #[rustc_const_stable(feature = "io_safety", since = "1.63.0")]
150 #[stable(feature = "io_safety", since = "1.63.0")]
151 pub const unsafe fn borrow_raw(handle: RawHandle) -> Self {
152 Self { handle, _phantom: PhantomData }
153 }
154}
155
156#[stable(feature = "io_safety", since = "1.63.0")]
157impl TryFrom<HandleOrNull> for OwnedHandle {
158 type Error = NullHandleError;
159
160 #[inline]
161 fn try_from(handle_or_null: HandleOrNull) -> Result<Self, NullHandleError> {
162 let handle_or_null = ManuallyDrop::new(handle_or_null);
163 if handle_or_null.is_valid() {
164 Ok(unsafe { OwnedHandle::from_raw_handle(handle_or_null.0) })
166 } else {
167 Err(NullHandleError(()))
168 }
169 }
170}
171
172#[stable(feature = "io_safety", since = "1.63.0")]
173impl Drop for HandleOrNull {
174 #[inline]
175 fn drop(&mut self) {
176 if self.is_valid() {
177 unsafe {
178 let _ = sys::c::CloseHandle(self.0);
179 }
180 }
181 }
182}
183
184impl OwnedHandle {
185 #[stable(feature = "io_safety", since = "1.63.0")]
188 pub fn try_clone(&self) -> io::Result<Self> {
189 self.as_handle().try_clone_to_owned()
190 }
191}
192
193impl BorrowedHandle<'_> {
194 #[stable(feature = "io_safety", since = "1.63.0")]
197 pub fn try_clone_to_owned(&self) -> io::Result<OwnedHandle> {
198 self.duplicate(0, false, sys::c::DUPLICATE_SAME_ACCESS)
199 }
200
201 pub(crate) fn duplicate(
202 &self,
203 access: u32,
204 inherit: bool,
205 options: u32,
206 ) -> io::Result<OwnedHandle> {
207 let handle = self.as_raw_handle();
208
209 if handle.is_null() {
214 return unsafe { Ok(OwnedHandle::from_raw_handle(handle)) };
215 }
216
217 let mut ret = ptr::null_mut();
218 cvt(unsafe {
219 let cur_proc = sys::c::GetCurrentProcess();
220 sys::c::DuplicateHandle(
221 cur_proc,
222 handle,
223 cur_proc,
224 &mut ret,
225 access,
226 inherit as sys::c::BOOL,
227 options,
228 )
229 })?;
230 unsafe { Ok(OwnedHandle::from_raw_handle(ret)) }
231 }
232}
233
234#[stable(feature = "io_safety", since = "1.63.0")]
235impl TryFrom<HandleOrInvalid> for OwnedHandle {
236 type Error = InvalidHandleError;
237
238 #[inline]
239 fn try_from(handle_or_invalid: HandleOrInvalid) -> Result<Self, InvalidHandleError> {
240 let handle_or_invalid = ManuallyDrop::new(handle_or_invalid);
241 if handle_or_invalid.is_valid() {
242 Ok(unsafe { OwnedHandle::from_raw_handle(handle_or_invalid.0) })
244 } else {
245 Err(InvalidHandleError(()))
246 }
247 }
248}
249
250#[stable(feature = "io_safety", since = "1.63.0")]
251impl Drop for HandleOrInvalid {
252 #[inline]
253 fn drop(&mut self) {
254 if self.is_valid() {
255 unsafe {
256 let _ = sys::c::CloseHandle(self.0);
257 }
258 }
259 }
260}
261
262#[stable(feature = "io_safety", since = "1.63.0")]
266#[derive(Debug, Clone, PartialEq, Eq)]
267pub struct NullHandleError(());
268
269#[stable(feature = "io_safety", since = "1.63.0")]
270impl fmt::Display for NullHandleError {
271 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
272 "A HandleOrNull could not be converted to a handle because it was null".fmt(fmt)
273 }
274}
275
276#[stable(feature = "io_safety", since = "1.63.0")]
277impl crate::error::Error for NullHandleError {}
278
279#[stable(feature = "io_safety", since = "1.63.0")]
284#[derive(Debug, Clone, PartialEq, Eq)]
285pub struct InvalidHandleError(());
286
287#[stable(feature = "io_safety", since = "1.63.0")]
288impl fmt::Display for InvalidHandleError {
289 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
290 "A HandleOrInvalid could not be converted to a handle because it was INVALID_HANDLE_VALUE"
291 .fmt(fmt)
292 }
293}
294
295#[stable(feature = "io_safety", since = "1.63.0")]
296impl crate::error::Error for InvalidHandleError {}
297
298#[stable(feature = "io_safety", since = "1.63.0")]
299impl AsRawHandle for BorrowedHandle<'_> {
300 #[inline]
301 fn as_raw_handle(&self) -> RawHandle {
302 self.handle
303 }
304}
305
306#[stable(feature = "io_safety", since = "1.63.0")]
307impl AsRawHandle for OwnedHandle {
308 #[inline]
309 fn as_raw_handle(&self) -> RawHandle {
310 self.handle
311 }
312}
313
314#[stable(feature = "io_safety", since = "1.63.0")]
315impl IntoRawHandle for OwnedHandle {
316 #[inline]
317 fn into_raw_handle(self) -> RawHandle {
318 ManuallyDrop::new(self).handle
319 }
320}
321
322#[stable(feature = "io_safety", since = "1.63.0")]
323impl FromRawHandle for OwnedHandle {
324 #[inline]
325 unsafe fn from_raw_handle(handle: RawHandle) -> Self {
326 Self { handle }
327 }
328}
329
330impl HandleOrNull {
331 #[stable(feature = "io_safety", since = "1.63.0")]
346 #[inline]
347 pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
348 Self(handle)
349 }
350
351 fn is_valid(&self) -> bool {
352 !self.0.is_null()
353 }
354}
355
356impl HandleOrInvalid {
357 #[stable(feature = "io_safety", since = "1.63.0")]
373 #[inline]
374 pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
375 Self(handle)
376 }
377
378 fn is_valid(&self) -> bool {
379 self.0 != sys::c::INVALID_HANDLE_VALUE
380 }
381}
382
383#[stable(feature = "io_safety", since = "1.63.0")]
384impl Drop for OwnedHandle {
385 #[inline]
386 fn drop(&mut self) {
387 unsafe {
388 let _ = sys::c::CloseHandle(self.handle);
389 }
390 }
391}
392
393#[stable(feature = "io_safety", since = "1.63.0")]
394impl fmt::Debug for BorrowedHandle<'_> {
395 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
396 f.debug_struct("BorrowedHandle").field("handle", &self.handle).finish()
397 }
398}
399
400#[stable(feature = "io_safety", since = "1.63.0")]
401impl fmt::Debug for OwnedHandle {
402 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
403 f.debug_struct("OwnedHandle").field("handle", &self.handle).finish()
404 }
405}
406
407macro_rules! impl_is_terminal {
408 ($($t:ty),*$(,)?) => {$(
409 #[stable(feature = "is_terminal", since = "1.70.0")]
410 impl io::IsTerminal for $t {
411 #[inline]
412 fn is_terminal(&self) -> bool {
413 crate::sys::io::is_terminal(self)
414 }
415 }
416 )*}
417}
418
419impl_is_terminal!(BorrowedHandle<'_>, OwnedHandle);
420
421#[stable(feature = "io_safety", since = "1.63.0")]
423pub trait AsHandle {
424 #[cfg_attr(windows, doc = "```no_run")]
429 #[cfg_attr(not(windows), doc = "```ignore (needs windows)")]
430 #[stable(feature = "io_safety", since = "1.63.0")]
439 fn as_handle(&self) -> BorrowedHandle<'_>;
440}
441
442#[stable(feature = "io_safety", since = "1.63.0")]
443impl<T: AsHandle + ?Sized> AsHandle for &T {
444 #[inline]
445 fn as_handle(&self) -> BorrowedHandle<'_> {
446 T::as_handle(self)
447 }
448}
449
450#[stable(feature = "io_safety", since = "1.63.0")]
451impl<T: AsHandle + ?Sized> AsHandle for &mut T {
452 #[inline]
453 fn as_handle(&self) -> BorrowedHandle<'_> {
454 T::as_handle(self)
455 }
456}
457
458#[stable(feature = "as_windows_ptrs", since = "1.71.0")]
459impl<T: AsHandle + ?Sized> AsHandle for crate::sync::Arc<T> {
472 #[inline]
473 fn as_handle(&self) -> BorrowedHandle<'_> {
474 (**self).as_handle()
475 }
476}
477
478#[stable(feature = "as_windows_ptrs", since = "1.71.0")]
479impl<T: AsHandle + ?Sized> AsHandle for crate::rc::Rc<T> {
480 #[inline]
481 fn as_handle(&self) -> BorrowedHandle<'_> {
482 (**self).as_handle()
483 }
484}
485
486#[unstable(feature = "unique_rc_arc", issue = "112566")]
487impl<T: AsHandle + ?Sized> AsHandle for crate::rc::UniqueRc<T> {
488 #[inline]
489 fn as_handle(&self) -> BorrowedHandle<'_> {
490 (**self).as_handle()
491 }
492}
493
494#[stable(feature = "as_windows_ptrs", since = "1.71.0")]
495impl<T: AsHandle + ?Sized, A: Allocator> AsHandle for Box<T, A> {
496 #[inline]
497 fn as_handle(&self) -> BorrowedHandle<'_> {
498 (**self).as_handle()
499 }
500}
501
502#[stable(feature = "io_safety", since = "1.63.0")]
503impl AsHandle for BorrowedHandle<'_> {
504 #[inline]
505 fn as_handle(&self) -> BorrowedHandle<'_> {
506 *self
507 }
508}
509
510#[stable(feature = "io_safety", since = "1.63.0")]
511impl AsHandle for OwnedHandle {
512 #[inline]
513 fn as_handle(&self) -> BorrowedHandle<'_> {
514 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
518 }
519}
520
521#[stable(feature = "io_safety", since = "1.63.0")]
522impl AsHandle for fs::File {
523 #[inline]
524 fn as_handle(&self) -> BorrowedHandle<'_> {
525 self.as_inner().as_handle()
526 }
527}
528
529#[stable(feature = "io_safety", since = "1.63.0")]
530impl From<fs::File> for OwnedHandle {
531 #[inline]
533 fn from(file: fs::File) -> OwnedHandle {
534 file.into_inner().into_inner().into_inner()
535 }
536}
537
538#[stable(feature = "io_safety", since = "1.63.0")]
539impl From<OwnedHandle> for fs::File {
540 #[inline]
542 fn from(owned: OwnedHandle) -> Self {
543 Self::from_inner(FromInner::from_inner(FromInner::from_inner(owned)))
544 }
545}
546
547#[stable(feature = "io_safety", since = "1.63.0")]
548impl AsHandle for io::Stdin {
549 #[inline]
550 fn as_handle(&self) -> BorrowedHandle<'_> {
551 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
552 }
553}
554
555#[stable(feature = "io_safety", since = "1.63.0")]
556impl<'a> AsHandle for io::StdinLock<'a> {
557 #[inline]
558 fn as_handle(&self) -> BorrowedHandle<'_> {
559 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
560 }
561}
562
563#[stable(feature = "io_safety", since = "1.63.0")]
564impl AsHandle for io::Stdout {
565 #[inline]
566 fn as_handle(&self) -> BorrowedHandle<'_> {
567 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
568 }
569}
570
571#[stable(feature = "io_safety", since = "1.63.0")]
572impl<'a> AsHandle for io::StdoutLock<'a> {
573 #[inline]
574 fn as_handle(&self) -> BorrowedHandle<'_> {
575 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
576 }
577}
578
579#[stable(feature = "io_safety", since = "1.63.0")]
580impl AsHandle for io::Stderr {
581 #[inline]
582 fn as_handle(&self) -> BorrowedHandle<'_> {
583 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
584 }
585}
586
587#[stable(feature = "io_safety", since = "1.63.0")]
588impl<'a> AsHandle for io::StderrLock<'a> {
589 #[inline]
590 fn as_handle(&self) -> BorrowedHandle<'_> {
591 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
592 }
593}
594
595#[stable(feature = "io_safety", since = "1.63.0")]
596impl AsHandle for crate::process::ChildStdin {
597 #[inline]
598 fn as_handle(&self) -> BorrowedHandle<'_> {
599 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
600 }
601}
602
603#[stable(feature = "io_safety", since = "1.63.0")]
604impl From<crate::process::ChildStdin> for OwnedHandle {
605 #[inline]
607 fn from(child_stdin: crate::process::ChildStdin) -> OwnedHandle {
608 unsafe { OwnedHandle::from_raw_handle(child_stdin.into_raw_handle()) }
609 }
610}
611
612#[stable(feature = "io_safety", since = "1.63.0")]
613impl AsHandle for crate::process::ChildStdout {
614 #[inline]
615 fn as_handle(&self) -> BorrowedHandle<'_> {
616 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
617 }
618}
619
620#[stable(feature = "io_safety", since = "1.63.0")]
621impl From<crate::process::ChildStdout> for OwnedHandle {
622 #[inline]
624 fn from(child_stdout: crate::process::ChildStdout) -> OwnedHandle {
625 unsafe { OwnedHandle::from_raw_handle(child_stdout.into_raw_handle()) }
626 }
627}
628
629#[stable(feature = "io_safety", since = "1.63.0")]
630impl AsHandle for crate::process::ChildStderr {
631 #[inline]
632 fn as_handle(&self) -> BorrowedHandle<'_> {
633 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
634 }
635}
636
637#[stable(feature = "io_safety", since = "1.63.0")]
638impl From<crate::process::ChildStderr> for OwnedHandle {
639 #[inline]
641 fn from(child_stderr: crate::process::ChildStderr) -> OwnedHandle {
642 unsafe { OwnedHandle::from_raw_handle(child_stderr.into_raw_handle()) }
643 }
644}
645
646#[stable(feature = "io_safety", since = "1.63.0")]
647impl<T> AsHandle for crate::thread::JoinHandle<T> {
648 #[inline]
649 fn as_handle(&self) -> BorrowedHandle<'_> {
650 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
651 }
652}
653
654#[stable(feature = "io_safety", since = "1.63.0")]
655impl<T> From<crate::thread::JoinHandle<T>> for OwnedHandle {
656 #[inline]
657 fn from(join_handle: crate::thread::JoinHandle<T>) -> OwnedHandle {
658 join_handle.into_inner().into_handle().into_inner()
659 }
660}
661
662#[stable(feature = "anonymous_pipe", since = "1.87.0")]
663impl AsHandle for io::PipeReader {
664 fn as_handle(&self) -> BorrowedHandle<'_> {
665 self.0.as_handle()
666 }
667}
668
669#[stable(feature = "anonymous_pipe", since = "1.87.0")]
670impl From<io::PipeReader> for OwnedHandle {
671 fn from(pipe: io::PipeReader) -> Self {
672 pipe.into_inner().into_inner()
673 }
674}
675
676#[stable(feature = "anonymous_pipe", since = "1.87.0")]
677impl AsHandle for io::PipeWriter {
678 fn as_handle(&self) -> BorrowedHandle<'_> {
679 self.0.as_handle()
680 }
681}
682
683#[stable(feature = "anonymous_pipe", since = "1.87.0")]
684impl From<io::PipeWriter> for OwnedHandle {
685 fn from(pipe: io::PipeWriter) -> Self {
686 pipe.into_inner().into_inner()
687 }
688}
689
690#[stable(feature = "anonymous_pipe", since = "1.87.0")]
691impl From<OwnedHandle> for io::PipeReader {
692 fn from(owned_handle: OwnedHandle) -> Self {
693 Self::from_inner(FromInner::from_inner(owned_handle))
694 }
695}
696
697#[stable(feature = "anonymous_pipe", since = "1.87.0")]
698impl From<OwnedHandle> for io::PipeWriter {
699 fn from(owned_handle: OwnedHandle) -> Self {
700 Self::from_inner(FromInner::from_inner(owned_handle))
701 }
702}